<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="js/vue.js"></script>
    <style>
        .box {
            border: 1px solid #cccccc;
        }
    </style>
</head>

<body>
    <div id="app">
        <h3>父组件</h3>
        <p>msg:{{ msg }}</p>
        <p>num:{{ num }}</p>
        <p>message:{{ message }}</p>
        <input type="text"v-model="message">
        <p>user:{{ user }}</p>
        <p>arr:{{ arr }}</p>
        <!-- <comp-a :message=" '匿名变量' "></comp-a>         -->
        <hr>
        <comp-a itany="网博" aa="aaa" :number=" num " :message=" message " :user=" user " :arr="arr"></comp-a>
    </div>
    <template id="compa">
        <div class="box">
            <h3>子组件</h3>
            <p>info:{{ info }}</p>
            <p>num:{{ num }}</p>
            <p>message:{{ message }}</p>
            <input type="text" name="" id="" v-model="message">
            <hr>
            <input type="button" value="$parent" @click="printParent()">
            <input type="button" value="$attrs" @click="printAttrs()">
            <hr>
            <p>user:{{ user.name }}</p>
        </div>
    </template>
</body>
<script>
    /*
        1、借助 vm.$paren 实现父向子进行数据传递
            vm.$paren 是vue提供的一个组件实例属性
                描述当前组件所在的 父组件 实例对象
                => 在子组件范围了可以通过主动获取方式从父组件中调用数据变量
            * 只能获取到父组件数据仓库中已知的属性变量
            * 不具有响应式数据功能
        2、借助于 vm.$attrs 实现父向子进行数据传递
            vm.$attrs 是vue 提供的一个组件实例属性
                获取当前组件调用时标签上定义的自定义属性数据变量
            * 不具有响应式数据功能
        3、组件配置属性 props
            props 实现的是 响应式 父组件向子组件进行数据传递的功能
            + 属性绑定，数据拦截
                属性绑定：参照 vm.$attrs 可以获取组件标签自定义属性的方式，进行相同操作
                数据拦截（props）：在子组件进行数据劫持处理时，直接将vm.$attrs 中相关被拦截的变量进行加载
                         并在子组件结合 vm.$parent 关联响应数据关系
            + props 取值 Array<string> | Object
                  - 取值为数组 数组的每个元素用于描述被拦截的 自定义属性名
                  - 取值为 Object ，可以实现拦截数据校验和默认值定义
            + props 时vue实例的另外一个数据仓库，具有相关的数据仓库功能
                    !!! 仓库中的属性为只读属性
    */

    Vue.component("CompA", {
        template: "#compa",
        data(){
            return {
                info:"",
                num:0
            }
        },
        // props:["message","user"],
        props:{
            // key 描述需要被拦截的属性名称
            // value 取值为 Object 值，对象中通过 vue定义的属性描述所要完成功能
            message:{
                // 限制对组件传递的数据必须是何种数据类型
                // 为开发人员提供 组件调用的时候，属性定义的取值规范
                // Type的取值为 JS 中数据类型构造器的名称
                //  String Number Boolean Array Object
                type:String,
                // 取值为 boolean 值，默认 false
                // 限制组件页面调用时，该属性是否为毕传变量
                required:true,
                default:"默认值"
            },
            user:{
                type:Object,
                // 描述当前未传递该属性是，取值为 {}
                // 只有被拦截的数据取值类型为 Object|Array 才需要以方法定义方式返回默认值
                default(){
                    return {};
                }
            },
            arr:{
                // 自定义数据校验规则，方法默认存在一个参数，参数为父组件传递的数据
                // 通过方法 return true|false 描述校验是否通过
                validator(value){
                    console.log(value);
                    if(value.length<4){
                        return false
                    }else{
                        return true;
                    }
                }
            }
        },
        methods: {
            printParent(){
                console.log(this.$parent);
                console.log(this.$parent.msg);
                this.info = this.$parent.msg;
            },
            printAttrs(){
                console.log(this.$attrs);
                // 获取当前组件 props 中拦截的数据对象
                console.log(this.$props);
            }
        },
        mounted() {
            this.info = this.$parent.msg;
            this.num = this.$attrs.number;
        },
    })

    new Vue({
        el: '#app',
        data: {
            msg: "字符串",
            num: 123,
            message:undefined,
            user: undefined,
            arr: [1, 2, 3,4,5]
        },
        mounted() {
            setTimeout(() => {
                this.msg = "新字符串";
                this.num = 100000;
                this.message = "props字符串"
                this.user = {
                    name:"tom"
                }
            }, 6000);
        },
    });
</script>

</html>